<?php

namespace Xin\Menu\ThinkPHP;

use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Model;
use Xin\Menu\AbstractDBRepository;

class ModelRepository extends AbstractDBRepository
{
	/**
	 * 构造一个新的查询器
	 * @return Query
	 */
	protected function newQuery()
	{
		$modelClass = $this->getConfig('model', DatabaseMenu::class);

		return value(new $modelClass);
	}

	/**
	 * 使用自定义查询
	 * @return mixed
	 */
	protected function withCustomQuery()
	{
		$query = $this->newQuery();

		$queryCallback = $this->getConfig('query');
		if ($queryCallback) {
			$query = call_user_func($queryCallback, $query);
		}

		return $query;
	}

	/**
	 * 支持搜索的查询器
	 * @param array $search
	 * @return Query
	 */
	protected function newQueryWithSearch(array $search = [])
	{

		return $this->withCustomQuery()->withSearch(array_keys($search), $search);
	}

	/**
	 * @inheritDoc
	 * @throws DataNotFoundException
	 * @throws DbException
	 * @throws ModelNotFoundException
	 */
	public function all(array $search = [])
	{
		$items = $this->newQueryWithSearch($search)->order('sort')->select();

		return $this->optimizeItems($items);
	}

	/**
	 * @inheritDoc
	 * @throws DataNotFoundException
	 * @throws DbException
	 * @throws ModelNotFoundException
	 */
	public function get($identifier)
	{
		$item = $this->withCustomQuery()->whereIn('id', $identifier)->find();
		if (empty($item)) {
			return null;
		}

		return $this->optimizeItem($item);
	}

	/**
	 * 优化返回的结果集
	 * @param Collection $items
	 * @return array
	 */
	protected function optimizeItems(Collection $items)
	{
		return $items->map(function (Model $item) {
			return $this->optimizeItem($item);
		})->toArray();
	}

	/**
	 * 优化返回的结果
	 * @param Model $item
	 * @return array
	 */
	protected function optimizeItem(Model $item)
	{
		$item = $item->toArray();
		return $item;
	}

	/**
	 * @inheritDoc
	 */
	public function insert(array $data)
	{
		$writerCallback = $this->getConfig('writer');
		if ($writerCallback) {
			call_user_func_array($writerCallback, [&$data]);
		}

		$builder = $this->newQuery();
		$data['id'] = $builder->insertGetId($data);

		return $data;
	}

	/**
	 * @inheritDoc
	 * @throws DataNotFoundException
	 * @throws DbException
	 * @throws ModelNotFoundException
	 */
	public function update($identifier, array $data)
	{
		// 构建查询器
		$builder = $this->withCustomQuery();

		// 查询数据库数据
		$info = $builder->where('id', $identifier)->findOrFail();
		$info = (array)$info;

		$builder->where('id', $identifier)->update($data);

		return array_merge($info, $data);
	}

	/**
	 * @inheritDoc
	 * @throws DataNotFoundException
	 * @throws DbException
	 * @throws ModelNotFoundException
	 */
	public function delete($identifier)
	{
		$query = $this->newQuery();

		// 查询要删除的数据是否存在
		return $query->when(is_array($identifier), function ($query) use ($identifier) {
			$query->whereIn('id', $identifier);
		}, function ($query) use ($identifier) {
			$query->where('id', $identifier);
		})->select()->map(function (Model $item) {
			$item->delete();
			return (array)$item;
		});
	}

	/**
	 * 删除App
	 * @param string $app
	 * @return mixed
	 * @throws DataNotFoundException
	 * @throws DbException
	 * @throws ModelNotFoundException
	 */
	public function deleteByApp(string $app)
	{
		$query = $this->newQuery();

		// 查询要删除的数据是否存在
		return $query->where('app', $app)->select()->map(function (Model $item) {
			$item->delete();
			return (array)$item;
		});
	}

	/**
	 * 删除所有菜单
	 */
	public function deleteAll()
	{
		$this->withCustomQuery()->delete();
	}
}
